package cn.demoncat.util.lang;

import cn.demoncat.util.lang.constant.CharConstant;
import cn.demoncat.util.lang.constant.SystemConstant;
import cn.demoncat.util.lang.entity.SystemInfo;
import cn.demoncat.util.web.IpUtil;
import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.awt.*;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryUsage;
import java.lang.management.ThreadMXBean;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 系统工具
 *
 * @author 延晓磊
 * @since 2021年07月18日
 */
public class SystemUtil {

    private static final Logger LOG = LoggerFactory.getLogger(SystemUtil.class);


    /**
     * 获取系统属性/环境变量
     *
     * @param name
     * @return
     */
    public static String get(String name) {
        String value = null;
        try {
            // 获取系统属性
            value = System.getProperty(name);
            if (value == null) {
                // 获取环境变量
                value = System.getenv(name);
            }
        } catch (SecurityException e) {
            LOG.warn("获取系统属性/环境变量失败：{}", name, e);
        }
        return value;
    }

    /**
     * 获取系统信息
     *
     * @return
     *
     * @author 延晓磊
     * @since 2022年06月23日
     */
    public static SystemInfo getInfo(){
        return SystemInfo.getInstance();
    }

    /**
     * 获取JVM最大内存
     *
     * @return
     */
    public static long getMaxMemory() {
        return Runtime.getRuntime().maxMemory();
    }

    /**
     * 获取JVM已分配内存
     *
     * @return
     */
    public static long getTotalMemory() {
        return Runtime.getRuntime().totalMemory();
    }

    /**
     * 获取JVM已分配内存中的剩余空间
     *
     * @return
     */
    public static long getFreeMemory() {
        return Runtime.getRuntime().freeMemory();
    }

    /**
     * 获取JVM最大可用内存
     *
     * @return
     */
    public static long getUsableMemory() {
        return getMaxMemory() - getTotalMemory() + getFreeMemory();
    }

    /**
     * 获取JVM堆内存
     *
     * @return
     */
    public static MemoryUsage getHeapMemory(){
        return ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
    }

    /**
     * 获取JVM非堆内存
     *
     * @return
     */
    public static MemoryUsage getNonHeapMemory(){
        return ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage();
    }

    /**
     * 获取JVM进程ID
     *
     * @return
     */
    public static String getPid(){
        String vmName = ManagementFactory.getRuntimeMXBean().getName();
        return vmName.substring(0, vmName.indexOf(CharConstant.AT));
    }

    /**
     * 获取JVM启动时长
     *
     * @return
     */
    public static long getUptime(){
        return ManagementFactory.getRuntimeMXBean().getUptime();
    }

    /**
     * 获取JVM启动时间
     *
     * @return 时间戳
     */
    public static long getStartTimestamp(){
        return ManagementFactory.getRuntimeMXBean().getStartTime();
    }

    /**
     * 获取JVM启动时间
     *
     * @return 时间
     */
    public static LocalDateTime getStartTime(){
        return LocalDateUtil.toLocalDateTime(ManagementFactory.getRuntimeMXBean().getStartTime());
    }

    /**
     * 获取JVM已加载的类总数
     *
     * @return
     */
    public static long getLoadedClassCount(){
        return ManagementFactory.getClassLoadingMXBean().getLoadedClassCount();
    }

    /**
     * 获取JVM线程信息
     *
     * @return
     */
    public static ThreadMXBean getThread() {
        return ManagementFactory.getThreadMXBean();
    }

    /**
     * 获取JVM线程总数
     *
     * @return 返回当前活跃的线程数量，包括守护线程和非守护线程
     */
    public static int getThreadCount(){
        return getThread().getThreadCount();
    }

    /**
     * 获取JVM守护线程总数
     *
     * @return 返回当前活跃的守护线程数量
     */
    public static int getDaemonThreadCount(){
        return getThread().getDaemonThreadCount();
    }

    /**
     * 获取JVM线程峰值数
     *
     * @return 返回自JVM启动以来的峰值活动线程数。
     */
    public static int getPeakThreadCount(){
        return getThread().getPeakThreadCount();
    }

    /**
     * 获取JVM线程启动总数
     *
     * @return 返回自JVM启动以来创建和启动的线程总数。
     */
    public static long getTotalStartedThreadCount(){
        return getThread().getTotalStartedThreadCount();
    }

    /**
     * 获取系统信息-系统名称
     *
     * @return System.getProperty("os.name")
     */
    public static String getOsName(){
        // return ManagementFactory.getOperatingSystemMXBean().getName();
        return SystemConstant.OS_NAME;
    }

    /**
     * 获取系统信息-CPU名称
     *
     * @return System.getProperty("os.arch")
     */
    public static String getCpuName(){
        return ManagementFactory.getOperatingSystemMXBean().getArch();
    }

    /**
     * 获取系统信息-CPU处理器数（核数）
     *
     * @return
     */
    public static int getCpuProcessors(){
        return Runtime.getRuntime().availableProcessors();
        // return ManagementFactory.getOperatingSystemMXBean().getAvailableProcessors();
    }

    /**
     * 获取JAVA版本
     *
     * @return
     */
    public static String getJavaVersion(){
        return get(SystemConstant.PropertiesKey.VERSION);
    }

    /**
     * 获取JAVA HOME
     *
     * @return
     */
    public static String getJavaHome(){
        return get(SystemConstant.PropertiesKey.HOME);
    }

    /**
     * 获取本机IP
     *
     * @return
     */
    public static String getLocalIp(){
        return IpUtil.LOCAL_IP;
    }

    /**
     * 是否为Linux系统
     *
     * @return
     *
     * @author 延晓磊
     * @since 2022年05月11日
     */
    public static boolean isLinux(){
        return SystemConstant.OS_IS_LINUX;
    }

    /**
     * 获取字体
     *
     * @param family    非空时求交集
     *
     * @return 系统字体/交集字体
     * 
     * @author 延晓磊
     * @since 2022年06月22日
     */
    public static List<String> getFontFamily(String ... family){
        // 获取系统字体
        List<String> names = ArrayUtil.toList(GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames()) ;
        // 求交集
        if (ArrayUtils.isNotEmpty(family)) {
            List<String> intersection = new ArrayList<>(family.length);
            for (String s : family) {
                if (names.contains(s)) {
                    intersection.add(s);
                }
            }
            names = intersection;
        }
        return names;
    }

}
